{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   instant      dteday  season  yr  mnth  holiday  weekday  workingday  \\\n0        1  2011-01-01       1   0     1        0        6           0   \n1        2  2011-01-02       1   0     1        0        0           0   \n2        3  2011-01-03       1   0     1        0        1           1   \n3        4  2011-01-04       1   0     1        0        2           1   \n4        5  2011-01-05       1   0     1        0        3           1   \n\n   weathersit      temp     atemp       hum  windspeed  casual  registered  \\\n0           2  0.344167  0.363625  0.805833   0.160446     331         654   \n1           2  0.363478  0.353739  0.696087   0.248539     131         670   \n2           1  0.196364  0.189405  0.437273   0.248309     120        1229   \n3           1  0.200000  0.212122  0.590435   0.160296     108        1454   \n4           1  0.226957  0.229270  0.436957   0.186900      82        1518   \n\n    cnt  \n0   985  \n1   801  \n2  1349  \n3  1562  \n4  1600  \n<class 'pandas.core.frame.DataFrame'>\nRangeIndex: 731 entries, 0 to 730\nData columns (total 16 columns):\ninstant       731 non-null int64\ndteday        731 non-null object\nseason        731 non-null int64\nyr            731 non-null int64\nmnth          731 non-null int64\nholiday       731 non-null int64\nweekday       731 non-null int64\nworkingday    731 non-null int64\nweathersit    731 non-null int64\ntemp          731 non-null float64\natemp         731 non-null float64\nhum           731 non-null float64\nwindspeed     731 non-null float64\ncasual        731 non-null int64\nregistered    731 non-null int64\ncnt           731 non-null int64\ndtypes: float64(4), int64(11), object(1)\nmemory usage: 91.5+ KB\nNone\n          instant      season          yr        mnth     holiday     weekday  \\\ncount  731.000000  731.000000  731.000000  731.000000  731.000000  731.000000   \nmean   366.000000    2.496580    0.500684    6.519836    0.028728    2.997264   \nstd    211.165812    1.110807    0.500342    3.451913    0.167155    2.004787   \nmin      1.000000    1.000000    0.000000    1.000000    0.000000    0.000000   \n25%    183.500000    2.000000    0.000000    4.000000    0.000000    1.000000   \n50%    366.000000    3.000000    1.000000    7.000000    0.000000    3.000000   \n75%    548.500000    3.000000    1.000000   10.000000    0.000000    5.000000   \nmax    731.000000    4.000000    1.000000   12.000000    1.000000    6.000000   \n\n       workingday  weathersit        temp       atemp         hum   windspeed  \\\ncount  731.000000  731.000000  731.000000  731.000000  731.000000  731.000000   \nmean     0.683995    1.395349    0.495385    0.474354    0.627894    0.190486   \nstd      0.465233    0.544894    0.183051    0.162961    0.142429    0.077498   \nmin      0.000000    1.000000    0.059130    0.079070    0.000000    0.022392   \n25%      0.000000    1.000000    0.337083    0.337842    0.520000    0.134950   \n50%      1.000000    1.000000    0.498333    0.486733    0.626667    0.180975   \n75%      1.000000    2.000000    0.655417    0.608602    0.730209    0.233214   \nmax      1.000000    3.000000    0.861667    0.840896    0.972500    0.507463   \n\n            casual   registered          cnt  \ncount   731.000000   731.000000   731.000000  \nmean    848.176471  3656.172367  4504.348837  \nstd     686.622488  1560.256377  1937.211452  \nmin       2.000000    20.000000    22.000000  \n25%     315.500000  2497.000000  3152.000000  \n50%     713.000000  3662.000000  4548.000000  \n75%    1096.000000  4776.500000  5956.000000  \nmax    3410.000000  6946.000000  8714.000000  \n"
     ]
    }
   ],
   "source": [
    "# 1. 对连续型特征，可以用哪个函数可视化其分布？（给出你最常用的一个即可），并根据代码运行结果给出示例。（10分）\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "\n",
    "params = {\n",
    "    \"legend.fontsize\": \"x-large\",\n",
    "    \"figure.figsize\": (30, 10),\n",
    "    \"axes.labelsize\": \"x-large\",\n",
    "    \"axes.titlesize\": \"x-large\",\n",
    "    \"xtick.labelsize\": \"x-large\",\n",
    "    \"ytick.labelsize\": \"x-large\"\n",
    "}\n",
    "sns.set_style(\"whitegrid\")\n",
    "sns.set_context(\"talk\")\n",
    "plt.rcParams.update(params)\n",
    "pd.set_option(\"max_colwidth\", 600)\n",
    "\n",
    "\n",
    "train = pd.read_csv(\"data/day.csv\")\n",
    "\n",
    "# 先来数据探索一下\n",
    "print(train.head())\n",
    "print(train.info())\n",
    "print(train.describe())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 再来挑几个连续型特征\n",
    "numerical_features = [\"temp\", \"atemp\", \"hum\", \"windspeed\"]\n",
    "train_x_numerical = train[numerical_features]\n",
    "# 看一下直方图\n",
    "train_x_numerical.hist()\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2. 对两个连续型特征，可以用哪个函数得到这两个特征之间的相关性？根据代码运行结果，给出示例。（10分）\n",
    "\n",
    "# scatterplot\n",
    "sns.scatterplot(data=train[[\"temp\", \"atemp\"]], x=\"temp\", y=\"atemp\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# lineplot\n",
    "sns.lineplot(data=train[[\"temp\", \"atemp\"]], x=\"temp\", y=\"atemp\")\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# DateFrame.corr()和sns.heatmap()\n",
    "corr = train[[\"temp\", \"atemp\"]].corr()\n",
    "mask = np.array(corr)\n",
    "mask[np.tril_indices_from(mask)] = False\n",
    "sns.heatmap(data=corr, mask=mask, vmax=0.8, square=True, annot=True)\n",
    "plt.show()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   instant  season_1  season_2  season_3  season_4  mnth_1  mnth_2  mnth_3  \\\n0        1         1         0         0         0       1       0       0   \n1        2         1         0         0         0       1       0       0   \n2        3         1         0         0         0       1       0       0   \n3        4         1         0         0         0       1       0       0   \n4        5         1         0         0         0       1       0       0   \n\n   mnth_4  mnth_5  ...  weathersit_2  weathersit_3      temp     atemp  \\\n0       0       0  ...             1             0  0.355170  0.373517   \n1       0       0  ...             1             0  0.379232  0.360541   \n2       0       0  ...             0             0  0.171000  0.144830   \n3       0       0  ...             0             0  0.175530  0.174649   \n4       0       0  ...             0             0  0.209120  0.197158   \n\n        hum  windspeed  workingday  holiday  yr   cnt  \n0  0.828620   0.284606           0        0   0   985  \n1  0.715771   0.466215           0        0   0   801  \n2  0.449638   0.465740           1        0   0  1349  \n3  0.607131   0.284297           1        0   0  1562  \n4  0.449313   0.339143           1        0   0  1600  \n\n[5 rows x 35 columns]\n<class 'pandas.core.frame.DataFrame'>\nRangeIndex: 731 entries, 0 to 730\nData columns (total 35 columns):\ninstant         731 non-null int64\nseason_1        731 non-null uint8\nseason_2        731 non-null uint8\nseason_3        731 non-null uint8\nseason_4        731 non-null uint8\nmnth_1          731 non-null uint8\nmnth_2          731 non-null uint8\nmnth_3          731 non-null uint8\nmnth_4          731 non-null uint8\nmnth_5          731 non-null uint8\nmnth_6          731 non-null uint8\nmnth_7          731 non-null uint8\nmnth_8          731 non-null uint8\nmnth_9          731 non-null uint8\nmnth_10         731 non-null uint8\nmnth_11         731 non-null uint8\nmnth_12         731 non-null uint8\nweekday_0       731 non-null uint8\nweekday_1       731 non-null uint8\nweekday_2       731 non-null uint8\nweekday_3       731 non-null uint8\nweekday_4       731 non-null uint8\nweekday_5       731 non-null uint8\nweekday_6       731 non-null uint8\nweathersit_1    731 non-null uint8\nweathersit_2    731 non-null uint8\nweathersit_3    731 non-null uint8\ntemp            731 non-null float64\natemp           731 non-null float64\nhum             731 non-null float64\nwindspeed       731 non-null float64\nworkingday      731 non-null int64\nholiday         731 non-null int64\nyr              731 non-null int64\ncnt             731 non-null int64\ndtypes: float64(4), int64(5), uint8(26)\nmemory usage: 70.1 KB\nNone\n"
     ]
    }
   ],
   "source": [
    "# 对离散型特征进行one-hot encode，对连续型特征进行标准化\n",
    "from sklearn.preprocessing import MinMaxScaler\n",
    "\n",
    "categorical_features = [\"season\", \"mnth\", \"weekday\", \"weathersit\"]\n",
    "categorical_features_2 = [\"workingday\", \"holiday\", \"yr\"]\n",
    "numerical_features = [\"temp\", \"atemp\", \"hum\", \"windspeed\"]\n",
    "numerical_features_0 = [\"instant\"]\n",
    "numerical_features_2 = []\n",
    "y = [\"cnt\"]\n",
    "\n",
    "for col in categorical_features:\n",
    "    train[col] = train[col].astype(\"object\")\n",
    "train_categorical = pd.get_dummies(train[categorical_features])\n",
    "\n",
    "min_max_scale = MinMaxScaler()\n",
    "temp = min_max_scale.fit_transform(train[numerical_features])\n",
    "train_numerical = pd.DataFrame(data=temp, \n",
    "                               columns=numerical_features, \n",
    "                               index=train.index)\n",
    "\n",
    "train_x = pd.concat([train_categorical, train_numerical], \n",
    "                    axis=1,\n",
    "                    ignore_index=False)\n",
    "\n",
    "FE_train = pd.concat([train[numerical_features_0], train_x, train[categorical_features_2], \n",
    "                      train[numerical_features_2], train[y]],\n",
    "                     axis=1)\n",
    "FE_train.to_csv(\"out/FE_day.csv\", index=False)\n",
    "print(FE_train.head())\n",
    "print(FE_train.info())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The r2 score on test is:  0.7974821392737572\nThe r2 score on train is:  0.8590596231264104\n"
     ]
    }
   ],
   "source": [
    "from sklearn.linear_model import LinearRegression\n",
    "from sklearn.linear_model import RidgeCV\n",
    "from sklearn.linear_model import LassoCV\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.metrics import r2_score\n",
    "\n",
    "# 读取数据并切分成训练集和校验集\n",
    "df = pd.read_csv(\"out/FE_day.csv\")\n",
    "y = df[\"cnt\"]\n",
    "X = df.drop([\"cnt\"], axis=1)\n",
    "feat_names = X.columns\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, \n",
    "                                                    random_state=23,\n",
    "                                                    test_size=0.2)\n",
    "\n",
    "# 最小二乘线性回归\n",
    "lr = LinearRegression()\n",
    "lr.fit(X_train, y_train)\n",
    "y_test_pred_lr = lr.predict(X_test)\n",
    "y_train_pred_lr = lr.predict(X_train)\n",
    "fs = pd.DataFrame({\"columns\": list(feat_names), \n",
    "                   \"coef\": list((lr.coef_.T))})\n",
    "fs.sort_values(by=[\"coef\"], ascending=False)\n",
    "print(\"The r2 score on test is: \", r2_score(y_test, y_test_pred_lr))\n",
    "print(\"The r2 score on train is: \", r2_score(y_train, y_train_pred_lr))\n",
    "\n",
    "f, ax = plt.subplots(figsize=(40, 30))\n",
    "ax.hist(y_train - y_train_pred_lr, bins=40, label=\"Residuals Linear\",\n",
    "        color=\"b\", alpha=.5)\n",
    "ax.set_title(\"Histogram of Residuals\")\n",
    "ax.legend(loc=\"best\")\n",
    "plt.show()\n",
    "\n",
    "plt.figure(figsize=(40, 30))\n",
    "plt.scatter(y_train, y_train_pred_lr)\n",
    "plt.plot([-3, 3], [-3, 3], \"--k\")\n",
    "plt.axis(\"tight\")\n",
    "plt.xlabel(\"True Cnt\")\n",
    "plt.ylabel(\"Predicted Cnt\")\n",
    "plt.show()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The R2 score of Test is:  0.7975825697670086\nThe R2 score of Train is:  0.857317264201171\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mse_mean are  [607027.80952672 603190.83932406 602229.57735666 654812.84487252\n 993504.53945484]\nalphas are  [0.01, 0.1, 1, 10, 100]\nalpha is  1.0\n"
     ]
    }
   ],
   "source": [
    "# 岭回归/L2回归\n",
    "from sklearn.linear_model import RidgeCV\n",
    "\n",
    "alphas = [0.01, 0.1, 1, 10, 100]\n",
    "ridge = RidgeCV(alphas=alphas, store_cv_values=True)\n",
    "ridge.fit(X_train, y_train)\n",
    "y_train_pred_ridge = ridge.predict(X_train)\n",
    "y_test_pred_ridge = ridge.predict(X_test)\n",
    "print(\"The R2 score of Test is: \", r2_score(y_test, y_test_pred_ridge))\n",
    "print(\"The R2 score of Train is: \", r2_score(y_train, y_train_pred_ridge))\n",
    "\n",
    "mse_mean = np.mean(ridge.cv_values_, axis=0)\n",
    "plt.plot(np.log10(alphas), mse_mean.reshape(len(alphas), 1))\n",
    "plt.xlabel(\"log(alphas)\")\n",
    "plt.ylabel(\"mse_mean\")\n",
    "plt.show()\n",
    "\n",
    "print(\"mse_mean are \", mse_mean)\n",
    "print(\"alphas are \", alphas)\n",
    "print(\"alpha is \", ridge.alpha_)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Python37\\lib\\site-packages\\sklearn\\model_selection\\_split.py:1978: FutureWarning: The default value of cv will change from 3 to 5 in version 0.22. Specify it explicitly to silence this warning.\n  warnings.warn(CV_WARNING, FutureWarning)\nD:\\Python37\\lib\\site-packages\\sklearn\\linear_model\\coordinate_descent.py:471: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations. Duality gap: 32450083.31892383, tolerance: 145896.93484267354\n  tol, rng, random, positive)\nD:\\Python37\\lib\\site-packages\\sklearn\\linear_model\\coordinate_descent.py:471: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations. Duality gap: 96218283.67080821, tolerance: 145896.93484267354\n  tol, rng, random, positive)\nD:\\Python37\\lib\\site-packages\\sklearn\\linear_model\\coordinate_descent.py:471: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations. Duality gap: 96252178.81487237, tolerance: 145896.93484267354\n  tol, rng, random, positive)\nD:\\Python37\\lib\\site-packages\\sklearn\\linear_model\\coordinate_descent.py:471: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations. Duality gap: 108797027.66997474, tolerance: 148347.29783136246\n  tol, rng, random, positive)\nD:\\Python37\\lib\\site-packages\\sklearn\\linear_model\\coordinate_descent.py:471: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations. Duality gap: 108945140.88616863, tolerance: 148347.29783136246\n  tol, rng, random, positive)\nD:\\Python37\\lib\\site-packages\\sklearn\\linear_model\\coordinate_descent.py:471: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations. Duality gap: 92998844.0172317, tolerance: 146223.89907589744\n  tol, rng, random, positive)\nD:\\Python37\\lib\\site-packages\\sklearn\\linear_model\\coordinate_descent.py:471: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations. Duality gap: 96938410.268818, tolerance: 146223.89907589744\n  tol, rng, random, positive)\nD:\\Python37\\lib\\site-packages\\sklearn\\linear_model\\coordinate_descent.py:471: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations. Duality gap: 96537837.95206977, tolerance: 146223.89907589744\n  tol, rng, random, positive)\nD:\\Python37\\lib\\site-packages\\sklearn\\linear_model\\coordinate_descent.py:475: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations. Duality gap: 79525268.17590395, tolerance: 220346.25117654106\n  positive)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The R2 score on Test is  0.7965052594672429\nThe R2 score on Train is  0.858298313135833\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "alpha is  1.0\n"
     ]
    }
   ],
   "source": [
    "# LassoCV回归\n",
    "lasso = LassoCV(alphas=alphas)\n",
    "lasso.fit(X_train, y_train)\n",
    "y_test_pred_lasso = lasso.predict(X_test)\n",
    "y_train_pred_lasso = lasso.predict(X_train)\n",
    "\n",
    "print(\"The R2 score on Test is \", r2_score(y_test, y_test_pred_lasso))\n",
    "print(\"The R2 score on Train is \", r2_score(y_train, y_train_pred_lasso))\n",
    "\n",
    "mse = np.mean(lasso.mse_path_, axis=1)\n",
    "plt.plot(np.log10(lasso.alphas_), mse)\n",
    "plt.xlabel(\"log(alpha)\")\n",
    "plt.ylabel(\"mse\")\n",
    "plt.show()\n",
    "\n",
    "print(\"alpha is \", lasso.alpha_)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
